home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Utilities / Programming / EnterAct 3.5 / hAWK project / AWK Source / hAWK_recurse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-22  |  5.3 KB  |  199 lines  |  [TEXT/KEEN]

  1. /* hAWK_recurse.c -- could have been called hAWK_hAWK.c,
  2. implements the hAWK() function which allows hAWK to call itself.
  3.  
  4. Ala MultiFinder, variables with more than function scope are saved
  5. and restored.
  6. */
  7. /* Copyright © 1986, 1988, 1989 1991 the Free Software Foundation, Inc.
  8.  *         This file is part of GAWK, the GNU implementation of the
  9.  * AWK Progamming Language, modified for the Macintosh (also called hAWK).
  10.  *         GAWK is free software; you can redistribute or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 1, or any later version.
  13.  *         GAWK is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16.  * GNU General Public License for more details.
  17.  *         You should have received a copy of the GNU General Public License
  18.  * along with GAWK; see the file "COPYING hAWK". If not, write to
  19.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  * Written for THINK C 4 on the Macintosh by Ken Earle (Dynabyte) Aug 1991.
  21.  */
  22. #include "AWK.H"
  23.  
  24. /* If KEEPGOING is defined, execution will continue even if an error
  25. occurs during hAWK() call that would be fatal in the main call. */
  26. /*#define    KEEPGOING */
  27.  
  28. /* An instance of the HAWKstate struct is created for each recursive
  29. call to hAWK - it stores the state of the calling instance, for
  30. restoration afterwards. This is an ugly but effective way of treating
  31. global variables as local by stacking them up. */
  32. HAWKstatePtr    hs = NULL;
  33.  
  34. /* This (new) global variable allows the main hAWK routine to 
  35. determine if it is being called for the first time or not
  36. - less initialization is done for second and subsequent calls. */
  37. short        hAWKstackDepth = 0;
  38.  
  39. /* from ARRAY.C */
  40. extern struct search *assoc_scan_sort(NODE *symbol);
  41. extern struct search *assoc_next_sort(struct search *lookat);
  42. /* from AWK_MAIN.C */
  43. extern short AWKmain(short argc, char **argv);
  44.  
  45. /* hAWK_recurse.c functions */
  46. NODE *do_hAWK(NODE *tree);
  47. char **SetUpARGV(short *argcPtr, NODE *arr);
  48. void SaveHAWKstate(void);
  49. void RestoreHAWKstate(void);
  50.  
  51. /* Save current state, start hAWK over, restore state, return
  52. integer representing success(1) or failure(0).
  53. First and only argument is argv[] node array. argc is calculated.
  54. WARNING argv[] passed must be a user variable - fiddling with
  55. built-in ARGV and trying to pass it will not work?
  56. */
  57. NODE *do_hAWK(NODE *tree)
  58.     {
  59.     HAWKstatePtr    tempHSPtr;
  60.     NODE             *t1, *arr;
  61.     short                argc, result;
  62.     char            **argv;
  63.     
  64.     
  65.     /* retrieve argument argv[] node */
  66.     if (!tree) {
  67.         fatal("hAWK requires at least one argument");
  68.     }
  69.     t1 = tree->lnode;
  70.     arr = t1;
  71.     if (t1->type == Node_param_list)
  72.         arr = stack_ptr[t1->param_cnt];
  73.     if (arr->type != Node_var && arr->type != Node_var_array)
  74.         fatal("second argument of hAWK is not a variable");
  75.     argv = SetUpARGV(&argc, arr);
  76.     if (!argv)
  77.         {
  78.         fatal("argument of hAWK is indecipherable");
  79.         }
  80.     /* allocate new HAWKstate */
  81.     emalloc(tempHSPtr, HAWKstatePtr, sizeof(HAWKstate), "hAWK");
  82.     tempHSPtr->onebefore = hs;
  83.     hs = tempHSPtr;
  84.     ++hAWKstackDepth;
  85.     SaveHAWKstate();
  86. #ifdef KEEPGOING
  87.     if (!setjmp(envBuf))
  88.         {
  89.         AWKmain(argc, argv);
  90.         RestoreHAWKstate();
  91.         result = hAWKstackDepth;
  92.         }
  93.     else
  94.         {
  95.         RestoreHAWKstate();
  96.         SysBeep(2);
  97.         result = 0;
  98.         }
  99. #else
  100.     AWKmain(argc, argv);
  101.     RestoreHAWKstate();
  102.     result = hAWKstackDepth;
  103. #endif
  104.     tempHSPtr = hs;
  105.     hs = hs->onebefore;
  106.     free(tempHSPtr);
  107.     free(argv);
  108.     --hAWKstackDepth;
  109.     return tmp_number((AWKNUM)result);
  110.     }
  111.  
  112.  
  113. char **SetUpARGV(short *argcPtr, NODE *arr)
  114.     {
  115.     char            *temp, **argv;
  116.     short                argc = 0, numNull = 0;
  117.     struct             search *l;
  118.     long            j, k;
  119.     
  120.     /* determine argument count; this is a bit tricky since a program
  121.     may reuse an array to call "hAWK" repeatedly, and the array may
  122.     shrink; as a crude rule, ten null entries in a row is taken to
  123.     mean there are no more entries. */
  124.     for (j = 0; j < 5000; ++j)
  125.         {
  126.         temp = 
  127.         force_string(*assoc_lookup(arr, tmp_number((AWKNUM) (j))))->stptr;
  128.         ++argc;
  129.         if (*temp)
  130.             numNull = 0;
  131.         else
  132.             {
  133.             ++numNull;
  134.             if (numNull > 9)
  135.                 {
  136.                 argc -= numNull;
  137.                 break;
  138.                 }
  139.             }
  140.         }
  141.     if (argc == 0)
  142.         return(NULL);
  143.     
  144.     /* allocate argv[] */
  145.     emalloc(argv, char **, argc * sizeof(char *), "SetUpARGV");
  146.     /* fill argv[]: retrieve elements indexed 0 to argc-1 */
  147.     for (j = 0, k = argc; j < k; ++j)
  148.         {
  149.         argv[j] = 
  150.         force_string(*assoc_lookup(arr, tmp_number((AWKNUM) (j))))->stptr;
  151.         }
  152.     *argcPtr = argc;
  153.     return(argv);
  154.     }
  155.  
  156. void SaveHAWKstate()
  157.     {
  158.     extern void SaveCommonsInAwkH(void);
  159.     extern void SaveAwkTabVars(void);
  160.     extern void SaveEval(void);
  161.     extern void SaveField(void);
  162.     extern void SaveIO(void);
  163.     extern void SaveNode(void);
  164.     extern void SaveRegex(void);
  165.  
  166. #ifdef KEEPGOING
  167.     BlockMove((Ptr)envBuf, (Ptr)(hs->envBuf), sizeof(jmp_buf));
  168. #endif
  169.     SaveCommonsInAwkH();
  170.     SaveAwkTabVars();
  171.     SaveEval();
  172.     SaveField();
  173.     SaveIO();
  174.     SaveNode();
  175.     SaveRegex();
  176.     }
  177.  
  178. void RestoreHAWKstate()
  179.     {
  180.     extern void RestoreCommonsInAwkH(void);
  181.     extern void RestoreAwkTabVars(void);
  182.     extern void RestoreEval(void);
  183.     extern void RestoreField(void);
  184.     extern void RestoreIO(void);
  185.     extern void RestoreNode(void);
  186.     extern void RestoreRegex(void);
  187.  
  188. #ifdef KEEPGOING
  189.     BlockMove((Ptr)(hs->envBuf), (Ptr)envBuf, sizeof(jmp_buf));
  190. #endif
  191.     RestoreCommonsInAwkH();
  192.     RestoreAwkTabVars();
  193.     RestoreEval();
  194.     RestoreField();
  195.     RestoreIO();
  196.     RestoreNode();
  197.     RestoreRegex();
  198.     }
  199.